package no.uib.hplims.views.orders;

import java.util.ArrayList;
import java.util.Collection;

import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.ui.Button;
import com.vaadin.ui.AbstractSelect.MultiSelectMode;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.ColumnGenerator;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window.Notification;
import com.vaadin.ui.themes.Runo;

import no.uib.hplims.Controller;
import no.uib.hplims.MyVaadinApplication;
import no.uib.hplims.models.MyOrder;
import no.uib.hplims.tools.Icons;
import no.uib.hplims.views.AbstractParentTab;

public class OrderTab extends AbstractParentTab implements
		Button.ClickListener {

	private static final long serialVersionUID = 3759985927365980912L;

	private Controller controller = null;

	private Table orderList = null;
	private final ArrayList<Object> visibleColumnIds = new ArrayList<Object>();
	private final ArrayList<String> visibleColumnLabels = new ArrayList<String>();

	private Label numberOfItemsLabel = null;
	private Button newOrderButton = new Button("New Order");
	private Button refreshButton = null;
	private Button removeItemButton = null;
	
	private static String caption = "Orders";

	public OrderTab() {
		super(caption, Icons.orderTabIcon16);
		
		init();
	}
	
	@Override
	protected void init() {
		VerticalLayout tab = getMainTab();
		
		
		tab.addComponent(createToolbar());
		tab.addComponent(addEditToolbar());
		
		populateOrderList();
		
	}

	private HorizontalLayout createToolbar() {
		addListeners();
		HorizontalLayout hl = new HorizontalLayout();
		hl.setSpacing(true);
		newOrderButton.setIcon(Icons.newItemIcon16);
		hl.addComponent(newOrderButton);
		return hl;
	}

	private void populateOrderList() {
		// create table
		orderList = new Table();
		orderList.setStyleName(Runo.TABLE_SMALL);

		// Adding ItemClickListener to handle double clicks
		orderList.addListener(new ItemClickListener() {
			private static final long serialVersionUID = 875928070362720544L;

			// Handle doubleClick
			public void itemClick(ItemClickEvent event) {
				if (event.isDoubleClick()) {

					if (event.getItemId() != null) {
						MyOrder pojo = (MyOrder) event.getItemId();

						if (pojo != null) {
							getController().showOrder(pojo);
						}

					}
				}
			}
		});

		// Enable/disable removeItemButton, depending on if there are items
		// selected
		orderList.addListener(new Property.ValueChangeListener() {
			private static final long serialVersionUID = 2756053322821158334L;

			public void valueChange(ValueChangeEvent event) {
				Collection<?> items = (Collection<?>) event.getProperty()
						.getValue();
				removeItemButton.setEnabled(items.size() > 0);
			}
		});

		// Specify which columns are visible
		visibleColumnIds.add("id");
		visibleColumnIds.add("orderTitle");
		visibleColumnIds.add("numberOfPeptidesInOrder");
		visibleColumnIds.add("owner");
		visibleColumnIds.add("createdOn");

		// Give those columns readable names
		visibleColumnLabels.add("Order ID");
		visibleColumnLabels.add("Name");
		visibleColumnLabels.add("# Peptides");
		visibleColumnLabels.add("Owner");
		visibleColumnLabels.add("Created on");
		
		orderList.addGeneratedColumn("numberOfPeptidesInOrder", new ColumnGenerator() {

			private static final long serialVersionUID = 4896067428965968268L;

			public Object generateCell(Table source, Object itemId, Object columnId) {
				MyOrder order = (MyOrder) itemId;
				int size = order.size();
				return new Label("" + size);
			}
		});

		// connect data source
		orderList.setContainerDataSource(getController().getOrderContainer());

		updateItemsLabel();

		// Table size
		orderList.setPageLength(20);
		orderList.setSizeFull();

		// Customize table columns
		orderList.setVisibleColumns(visibleColumnIds.toArray());
		orderList.setColumnHeaders(visibleColumnLabels.toArray(new String[0]));

		// Set table properties
		orderList.setEditable(false);
		orderList.setMultiSelect(true);
		orderList.setMultiSelectMode(MultiSelectMode.DEFAULT);
		orderList.setSelectable(true);
		orderList.setWriteThrough(true);
		orderList.setImmediate(true);

		// turn on column reordering and collapsing
		orderList.setColumnReorderingAllowed(true);
		orderList.setColumnCollapsingAllowed(true);

		// Add table to OrderView
		getMainTab().addComponent(orderList);
	}

	private Component addEditToolbar() {
		final HorizontalLayout layout = new HorizontalLayout();
		layout.setSizeFull();

		final HorizontalLayout buttonLayout = new HorizontalLayout();

		refreshButton = new Button("Refresh");
		refreshButton.setIcon(Icons.refreshIcon16);
		refreshButton.addListener(this);
		buttonLayout.addComponent(refreshButton);

		removeItemButton = new Button("Remove Row");
		removeItemButton.setIcon(Icons.removeIcon16);
		removeItemButton.addListener(this);
		removeItemButton.setEnabled(false);
		buttonLayout.addComponent(removeItemButton);

		numberOfItemsLabel = new Label();
		numberOfItemsLabel.setSizeUndefined();

		layout.addComponent(buttonLayout);
		layout.addComponent(numberOfItemsLabel);
		layout.setComponentAlignment(numberOfItemsLabel, Alignment.BOTTOM_RIGHT);

		return layout;
	}

	private void addListeners() {
		newOrderButton.addListener(this);
	}

	private Controller getController() {
		// if controller hasn't been initialized, get application and
		// initialize it.
		if (controller == null) {
			MyVaadinApplication app = MyVaadinApplication.getInstance();
			controller = app.getController();
		}
		return controller;
	}

	private void refreshOrderContainer() {
		getController().refreshOrderContainer();
		updateItemsLabel();
	}

	public void buttonClick(ClickEvent event) {
		if (event.getButton().equals(newOrderButton)) {

			// New order button clicked
			getController().showOrder(null);

			updateItemsLabel();

		} else if (event.getButton() == refreshButton) {

			refreshOrderContainer();

		} else if (event.getButton() == removeItemButton) {
			final Object selection = orderList.getValue();

			if (selection == null) {
				return;
			}

			if (selection instanceof Collection) {
				final Collection selectionIndexes = (Collection) selection;
				for (final Object selectedIndex : selectionIndexes) {
					orderList.unselect(selectedIndex);
					MyOrder order = (MyOrder) selectedIndex;
					if (order.size() == 0) {
						getController().deleteOrder(order);
						updateItemsLabel();
					} else {
						getWindow().showNotification(
								"Unable to delete " + order.getOrderTitle()
										+ ".\n",
								"Order is not empty.<br/>This order has one or more peptide(s) bound to it."
										+ " Only empty orders can be deleted.",
								Notification.TYPE_ERROR_MESSAGE);
					}
				}
			}
		}
	}
	
	private void updateItemsLabel() {
		numberOfItemsLabel.setValue("Items: " + getController().getOrderContainer().size());
	}

	public void activated(Object... params) {
		// TODO Auto-generated method stub

	}

	public void deactivated(Object... params) {
		// TODO Auto-generated method stub

	}
	
	@Override
	public String toString() {
		return caption;
	}
}
